/* 
	Game.cpp
*/

#include "Game.h"

// get an arbitrary position on the board
const char Game::get_pos(const int i, const int j)
{
	return board[i][j];
}

const string Game::last_move()
{
	if(moves.size() < 1)
		return "";

	stringstream ss;

	ss << hex << moves.top().row << moves.top().col;

	return ss.str();
}

// valid move: within the bounds of the board && position 
// not currently taken
bool Game::validate_move(const int i, const int j)
{
	int row = i;
	int col = j;

	if( row < 1 || row > 15)
	{
		cerr << "Error: invalid row" << endl;
		return false;
	}
	if( col < 1 || col > 15)
	{
		cerr << "Error: invalid column" << endl;
		return false;
	}
	if(board[row-1][col-1] == BLANK)
		return true;
	else
		cerr << "Error: space taken" << endl;
		return false;
}

// move to position i,j with the player p
// also log the move for an undo call later
void Game::move(const int i, const int j, const char p)
{
	if(!validate_move(i, j))
		return;
		
	int row = i - 1;
	int col = j - 1;
	
	Move m(row, col, p);

	board[row][col] = p;

	log_move(m);
}

void Game::move(Move m)
{
	if(!validate_move(m.row, m.col))
		return;

	board[m.row][m.col] = m.piece;

	log_move(m);
}

// wrapper for the move stack
void Game::log_move(const Move m)
{
	moves.push(m);
}

// looks at the top and pops the last 2 moves
void Game::undo()
{
	if(moves.size() < 1)
	{
		cerr << "Error: no moves to undo" << endl;
		return;
	}
	
	Move p1 = moves.top();
	moves.pop();
	Move p2 = moves.top();
	moves.pop();

	board[p1.row][p1.col] = BLANK;
	board[p2.row][p2.col] = BLANK;
}

// gives the board as a string 
string Game::display()
{
	string s;
	stringstream ss;

	ss << ";  1 2 3 4 5 6 7 8 9 a b c d e f" << endl;
	
	for(int i = 0; i < 15; ++i)
	{
		ss << ";" << hex << i+1 << ' ';

		for(int j = 0; j < 15; ++j)
			ss << board[i][j] << ' ';

		ss << endl;
	}
	
	return ss.str();
}

// could display on the serverside, same as display except with
// std::out
void Game::display_server()
{
	cout << ";  1 2 3 4 5 6 7 8 9 a b c d e f" << endl;
	
	for(int i = 0; i < 15; ++i)
	{
		cout << ";" << hex << i+1 << " ";

		for(int j = 0; j < 15; ++j)
			cout << board[i][j] << " ";

		cout << endl;
	}
}

// =========================================================
// check functions
// =========================================================

// checks five in a row based on step arguments
bool Game::check_pos(int r, int c, int sx, int sy)
{
	char player = get_pos(r, c);

	for(int i = 1; i < 5; i++)
		if(get_pos((r+sx*i), (c+sy*i)) != player)
			return false;

	return true;
}

// checks the entire board and passes the correct args for 
// the stepwise function check_pos and then checks if there 
// is a tie (all positions filled)
int Game::check_state()
{

	for (int r = 0; r < 15; ++r)
	{
		for (int c = 0; c < 15; ++c)
		{
			char pos = get_pos(r,c);

			if(pos != BLANK)
			{
				if(r < 11)
					if(check_pos(r, c, 1, 0))
						return 1;
				if(c < 11)
				{
					if(check_pos(r, c, 0, 1))
						return 1;
					if(r < 11)
						if(check_pos(r, c, 1, 1))
							return 1;
				}

				if(c > 5 && r < 11)
					if(check_pos(r, c, 1, -1))
						return 1;
			}
		}
	}

	return check_tie();
}

// checks if there remains blank pieces
int Game::check_tie()
{
	for(int i = 0; i < 15; ++i)
		for(int j = 0; j < 15; ++j)
		{
			if(get_pos(i,j) == BLACK || get_pos(i,j) == WHITE)
				return 0;

		}

	return 2;
}
